# !/usr/bin/env python
#
# Copyright 2008 CPedia.com.
#
# New portions Copyright 2009, 2010 Rob Stenzinger 
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

__author__ = 'Ping Chen, Rob Stenzinger'

import os
import re

import logging

from google.appengine.api import users
from google.appengine.ext.webapp import template
from google.appengine.api import memcache

import copy
import time
import urlparse
import string
import util
import model

import simplejson


"""
This is currently the one and only rendering/merging of template + data helper
"""
class ViewPage(object):
    def __init__(self, cache_time=None):
        """Each ViewPage has a variable cache timeout"""
        if cache_time == None:
            config = util.get_config()
            self.cache_time = config["cache_time"]
        else:
            self.cache_time = cache_time

    def full_render(self, handler, template_file, params={}, page_object_parameter_name=""):
            #if(handler.request.uri.find('logout')==-1):  #if the page from logout, then don't need to append the google account to session.
            #    session.login_google_user()
            
            #todo: removing session as much as possible:
            session = None
                
            #default name and url value to use in a Login/Logout link in a given HTML template:
            #todo: consider a simple option when general user login is re-added to the project:
            #if not session.get_current_user():
            google_user = users.get_current_user()
            #if not users.is_current_user_admin():
            if not google_user:
                url = "/login"
                url_linktext = 'Sign in'
            else:
                url = "/logout"
                url_linktext = 'Sign out'
                

            #twitter_data = {}
            twitter_data = util.get_twitter_user_timeline(handler.config["twitter_user"])
            recent_comics = util.recent_comics()
            
            feed_data = util.get_feed_items(handler.config["more_news_feed_url"])
            
            fullscreen = None
            try:
                if handler and handler.nav_context and handler.nav_context["fullscreen"] == True:
                    fullscreen = True
            except:
                pass
            
            template_params = {
                "title": handler.config["title"],
                "list": None,
                'user': users.get_current_user(),#session.get_current_user(),
                'url': url,
                'url_linktext': url_linktext,
                'request': handler.request,
                "user_is_admin": users.is_current_user_admin(),
                "BLOG": handler.config,
                "tags": model.Tag.list(),
                "feeds": None,
                "delicious": None,
                "user_gravatar_url":util.getGravatarUrlByUser(users.get_current_user()), #was session
                "user_nickname":util.getUserNickname(users.get_current_user()), #was session
                'nav_context' : util.get_user_nav_context(handler), 
                'nav_context_options':util.get_user_nav_context_options(),   
                'entrytypeList':model.config_post_types,  
                'statusList':model.config_post_status_types,
                'statusDefault':model.config_post_status_default,    
                'twitter_data':twitter_data,          
                'feed_data':feed_data,          
                'recent_comics':recent_comics,     
                'fullscreen':fullscreen,     
                }
            template_params.update(params)
                        
            if page_object_parameter_name in ["blog","featured","page"]:
                override_nav_mode = None
                if page_object_parameter_name == "featured":
                    #override_nav_mode = "book-chapter"
                    override_nav_mode = "type"
                
                show_meta_nav = False
                if params and params[page_object_parameter_name] and params[page_object_parameter_name].entrytype == "comic":
                    show_meta_nav = True
                #    override_nav_mode = "comic"
                    
                #todo: finish nav filters for paging/browsing    
                filter_comics = True
                filter_blogs = True  
                if override_nav_mode in ["comic"]:
                    filter_blogs = True                    
                
                book_data = util.chapters_first_and_latest_list(params[page_object_parameter_name])    
                chapterList = util.nav_relative_chapter_list(params[page_object_parameter_name])  
                episodeList =  util.nav_relative_episode_list(params[page_object_parameter_name]) 
                url_relative_list = util.nav_relative_url_list(handler, params[page_object_parameter_name], override_nav_mode)
                navParams = {
                    'chapterList':chapterList,
                    'episodeList':episodeList,
                    'nav_relative_url_list' : url_relative_list,
                    'book_data' : book_data,
                    'show_meta_nav':show_meta_nav,
                    'filter_comics':filter_comics,            
                    'filter_blogs':filter_blogs,            
                    'current_page':params[page_object_parameter_name],
                }
                template_params.update(navParams)                                      

            try:
                if handler and handler.nav_context and handler.nav_context["format"] == "json":
                    # output safe values to JSON... 
                    result_object = {                                     
                        'url': url,
                        'url_linktext': url_linktext,
                        'nav_context' : util.get_user_nav_context(handler), 
                        'entrytypeList':model.config_post_types,  
                        'fullscreen':fullscreen,
                        'archiveList':params["archiveList"],
                        'bookList':params["bookList"],
                    }
                    result_object.update(navParams)
                    model.json_lightweight = True
                    return simplejson.dumps(result_object, default = model.to_json)
                else:
                    return template.render(template_file, template_params) 
            except:
                return template.render(template_file, template_params) 
                pass


    def render_or_get_cache(self, handler, template_file, template_params={}, page_object_parameter_name=""):
        """Checks if there's a non-stale cached version of this view, and if so, return it."""
        if self.cache_time:
            key = handler.request.url + str(users.get_current_user() != None) + str(users.is_current_user_admin())
            output = memcache.get(key)
            if not output:
                util.getLogger(__name__).debug("Couldn't find a cache for %s", key)
            else:
                util.getLogger(__name__).debug("Using cache for %s", template_file)
                return output

            output = self.full_render(handler, template_file, template_params, page_object_parameter_name)
            # Add a value if it doesn't exist in the cache, with a cache expiration of 1 hour.
            memcache.add(key=key, value=output, time=self.cache_time)
            return output

        return self.full_render(handler, template_file, template_params, page_object_parameter_name)


    """
    this is the method to call to render, other methods are internal to this class
    """
    def render(self, handler, template_name, params={}, template_folder="", page_object_parameter_name=""):
        dirname = os.path.dirname(__file__)

        try:
            if handler and handler.nav_context and handler.nav_context["fullscreen"] == True:
                # force use of fullscreen nav:
               template_name = "blog_view_fullscreen.html"
        except:
            pass
        
        template_file = None
        
        # this forces templates with names including "admin" and "login" to use default/non-custom templates
        if str(template_name).lower().find("admin") > -1 or str(template_name).lower().find("login") > -1:
            template_file = os.path.join(dirname, os.path.join('templates', 'default', template_name))
        elif template_folder != "":
            try:
                template_file = os.path.join(dirname, os.path.join(os.path.join('templates', template_folder), template_name))
            except:
                pass
        
        if not os.path.isfile(template_file):
            template_file = None

        if template_file is None:
            template_file = os.path.join(dirname, os.path.join('templates', 'default', template_name))
                    
        #util.getLogger(__name__).debug("Using template at %s", template_file)
        #util.getLogger(__name__).debug("Using page parameter: %s", page_object_parameter_name)
        output = self.render_or_get_cache(handler, template_file, params, page_object_parameter_name)
        handler.response.out.write(output)
